package com.tuu.security;
import com.tuu.configBean.RedisUtil;
import com.tuu.pojo.Permission;
import com.tuu.utils.JwtTokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashSet;
@Component
@Slf4j
public class JwtAuthorizationTokenFilter extends OncePerRequestFilter {
    @Autowired
    @Qualifier("jwtUserDetailsService")
    private  UserDetailsService userDetailsService;
    @Autowired
    private  JwtTokenUtil jwtTokenUtil;
    @Value("${jwt.token}")
    private  String tokenHeader;
    @Value("${jwt.loginPage}")
    private  String loginPage;
    @Value("${jwt.AllAuths}")
    private  String allAuths;
    @Autowired
    private  RedisUtil redisUtil;
    public JwtAuthorizationTokenFilter(/*@Qualifier("jwtUserDetailsService") UserDetailsService userDetailsService,
                                       JwtTokenUtil jwtTokenUtil, @Value("${jwt.token}") String tokenHeader*/) {
        //this.userDetailsService = userDetailsService;
        //this.jwtTokenUtil = jwtTokenUtil;
        //this.tokenHeader = tokenHeader;
    }
//ServletException, IOException
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        log.info("执行到JwtAuthorizationTokenFilter");
        final String requestHeader = request.getHeader(this.tokenHeader);
        System.out.println("请求头是"+requestHeader+"全路径"+request.getRequestURL());
        String uid = null;
        String jwt = null;
        //&& requestHeader.startsWith("Bearer ")
        if (StringUtils.isNotBlank(requestHeader) ) {
            jwt = requestHeader;
            System.out.println("头不为空");
            try {
                uid = jwtTokenUtil.getUsernameFromToken(jwt);
            } catch (Exception e) {
                log.error("jwtFilter捕捉到错误"+e.getMessage());
            }
        }else{
            HashSet<Permission> permissions= null;
            try {
                permissions = (HashSet<Permission>) redisUtil.get(allAuths);
            } catch (Exception e) {
                log.info("错误"+e.getMessage());
            }
            if(permissions!=null){
                log.info("无token 进入匹配。。。");
                AntPathRequestMatcher matcher;
                boolean flag=false;
                for(Permission p:permissions){
                    matcher = new AntPathRequestMatcher(p.getUrl());
                    if (matcher.matches(request)) {
                        log.info("JwtAuthorizationTokenFilter url匹配成功。。。"+p.getUrl());
                        //说明该路径要权限 通知前面登陆
                        flag=true;
                        throw new IOException("权限不足，请登陆。。。");

                    }
                }
                if(!flag){
                    log.info("该路径不需要权限。任何人都可访问。。");
                    UserDetails userDetails=new SecurityUserDetails(null,null);
                    //在Security上下文中添加userDetails 不能直接添加,而是放到UsernamePasswordAuthenticationToken中
                    SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()));

                    chain.doFilter(request, response);
                }
            }
        }

//if (uid != null && SecurityContextHolder.getContext().getAuthentication() == null) {
        if (uid != null ) {
            System.out.println("token解析成功，拿到uid。。。"+uid);
            //返回用户所有的权限
            UserDetails userDetails = null;
            try {
                if (jwtTokenUtil.pureValidateToken(jwt,request)) {
                    log.info("进入上下文主体。。。jwt有效");
                    userDetails = userDetailsService.loadUserByUsername(uid);
                    //UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                    //SecurityContextHolder.getContext().setAuthentication(authentication);
                    //chain.doFilter(request, response);
                }else{
                    log.info("进入上下文主体。。。jwt无无无无效");
                    userDetails=new SecurityUserDetails(null,null);
                    //UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                    //SecurityContextHolder.getContext().setAuthentication(authentication);
                    //if(request.getRequestURI().equals(loginPage)){
                    //    chain.doFilter(request, response);
                    //}
                }
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                SecurityContextHolder.getContext().setAuthentication(authentication);
                System.out.println("到了.....jwtFilter的最后。。。");

            }catch (Exception e){
                //redis可能会宕机
                log.error("JwtAuthorizationTokenFilter token 过期:"+e.getMessage());
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                SecurityContextHolder.getContext().setAuthentication(authentication);
                System.out.println(request.getRequestURI());
                //if(request.getRequestURI().equals(loginPage)){
                  //  chain.doFilter(request, response);
                //}
                //throw new IOException("JwtAuthorizationTokenFilter token 过期:"+e.getMessage());
            }
            chain.doFilter(request, response);
        }
        //System.out.println("到了jwtFilter的最后。。。");
        //chain.doFilter(request, response);
    }
}